using EnvDTE;
using Microsoft.AspNetCore.SignalR;
using MultiAgentsClient.ChatDataStructures;
using MultiAgentsServer.Scripts.Database;
using MultiAgentsServer.Scripts.Hubs;
using MultiAgentsServer.Scripts.Services.DataModels;
using MultiAgentsServer.Scripts.Shared;
using MultiAgentsServer.Scripts.Shared.enums;
using MultiAgentsShared;
using static MultiAgentsServer.Scripts.Services.BehaviorTreeService;

namespace MultiAgentsServer.Scripts.Services;

public class OthersManager: ManagerBase
{
    private readonly UserCookieDataModel userCookieDataModel;
    private readonly IEventBus eventBus;
    private readonly DataBaseOperationService dataBaseOperationService;
    private readonly IHubContext<SignalRChatHub> signalRChatHubContext;
    private readonly IHubContext<SignalRUserSettingsHub> userSettingsHubContext;
    private readonly IHubContext<SignalRUserHub> userHubContext;
    private readonly IConfiguration configuration;

    public OthersManager(IEventBus eventBus,
        UserCookieDataModel userCookieDataModel,
        DataBaseOperationService dataBaseOperationService,
        IHubContext<SignalRChatHub> signalRChatHubContext,
        IHubContext<SignalRUserSettingsHub> userSettingsHubContext,
        IHubContext<SignalRUserHub> userHubContext,
        IConfiguration configuration) : base()
    {
        this.userCookieDataModel = userCookieDataModel;
        this.eventBus = eventBus;
        this.dataBaseOperationService = dataBaseOperationService;
        this.signalRChatHubContext = signalRChatHubContext;
        this.userSettingsHubContext = userSettingsHubContext;
        this.userHubContext = userHubContext;
        this.configuration = configuration;

        eventBus.Subscribe<RegisterCommand>(command => { Task.Run(() => RegisterRequestHandlerAsync(command)); });
        eventBus.Subscribe<ChangePasswordCommand>(command => { Task.Run(() => ChangePasswordCommandHandlerAsync(command)); });
        eventBus.Subscribe<LoginCommand>(command => { Task.Run(() => LoginRequestHandlerAsync(command)); });
        eventBus.Subscribe<SaveSessionIdCommand>(command => { Task.Run(() => SaveSessionIdCommandHandlerAsync(command)); });
        eventBus.Subscribe<AutoLoginCommand>(command => { Task.Run(() => AutoLoginRequestHandlerAsync(command)); });
        eventBus.Subscribe<LogoutCommand>(command => { Task.Run(() => LogoutRequestHandlerAsync(command)); });
        eventBus.Subscribe<FetchUserdataCommand>(command => { Task.Run(() => FetchUserdataRequestHandlerAsync(command)); });
        eventBus.Subscribe<FetchProjectSettingsCommnad>(command => { Task.Run(() => FetchProjectSettingsHandlerAsync(command)); });
        eventBus.Subscribe<SaveProjectSettingsCommnad>(command => { Task.Run(() => UpdateProjectSettingsHandlerAsync(command)); });
        eventBus.Subscribe<AllowToolCallChangedCommnad>(command => { Task.Run(() => AllowToolCallChangedCommnadHandlerAsync(command)); });

        eventBus.Subscribe<ArchiveChatRoomCommand>(command => { Task.Run(() => ArchiveChatroomRequestHandlerAsync(command)); });
        eventBus.Subscribe<DeleteChatRoomCommand>(command => { Task.Run(() => DeleteChatroomRequestHandlerAsync(command)); });
        eventBus.Subscribe<RenameChatRoomCommand>(command => { Task.Run(() => RenameChatRoomRequestHandlerAsync(command)); });

        eventBus.Subscribe<CreateProjectCommand>(command => { Task.Run(() => CreateProjectRequestHandlerAsync(command)); });
        eventBus.Subscribe<DeleteProjectCommand>(command => { Task.Run(() => DeleteProjectCommandHandlerAsync(command)); });
        eventBus.Subscribe<CreateChatRoomCommand>(command => { Task.Run(() => CreateChatroomRequestHandlerAsync(command)); });
        eventBus.Subscribe<SwitchChatRoomCommand>(command => { Task.Run(() => SwitchChatroomRequestHandlerAsync(command)); });
        eventBus.Subscribe<SwitchChatRoomBranchCommand>(command => { Task.Run(() => SwitchChatRoomBranchCommandHandlerAsync(command)); });

        eventBus.Subscribe<SubscriptonGitlabPullRequestCommand>(command => { Task.Run(() => AddPullRequestUserSubscription(command)); });
        eventBus.Subscribe<RecievePullRequestCommand>(command => { Task.Run(() => SavePullRequestContent(command)); });
        eventBus.Subscribe<RemoveConnectionCommand>(command => { Task.Run(() => RemoveConnectionCommandHandlerAsync(command)); });
    }

    private async Task RegisterRequestHandlerAsync(RegisterCommand command)
    {
        try
        {
            UserDB? user = dataBaseOperationService.GetUserByName(command.Username);
            string? invitationCode = dataBaseOperationService.GetManagerInvitationCode();
            StatusCode status = StatusCode.Status404;

            if (user != null)
            {
                status = StatusCode.Status4000;
            }
            else if (invitationCode == null || invitationCode != command.InvitationCode)
            {
                status = StatusCode.Status4001;
            }
            else
            {
                status = StatusCode.Status200;
                string salt = EncryptService.GenerateSalt(16);
                string passwordEncrypted = EncryptService.EncryptPassword(command.Password, salt, EncryptService.SHA256HashFunction);
                dataBaseOperationService.AddUser(command.Username, passwordEncrypted, salt);
            }

            await SignalRUserHub.RegisterApiResponse(userHubContext, command.ConnectionId, status);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
            await SignalRUserHub.RegisterApiResponse(userHubContext, command.ConnectionId, StatusCode.Status500);
        }
    }

    private async Task ChangePasswordCommandHandlerAsync(ChangePasswordCommand cmd)
    {
        if (userCookieDataModel.CheckUserAndSession(cmd.UserId, cmd.SessionId) == false)
        {
            return;
        }

        try
        {
            UserDB? user = dataBaseOperationService.GetUserById(cmd.UserId);
            StatusCode status = StatusCode.Status404;

            if ((user != null) && (user.Password == EncryptService.EncryptPassword(cmd.PreviousPassword, user.Salt, EncryptService.SHA256HashFunction)))
            {
                status = StatusCode.Status200;
                string salt = EncryptService.GenerateSalt(16);
                string passwordEncrypted = EncryptService.EncryptPassword(cmd.NewPassword, salt, EncryptService.SHA256HashFunction);
                dataBaseOperationService.ChangeUserPassword(cmd.UserId, passwordEncrypted, salt);
            }
            else
            {
                status = StatusCode.Status4006;
            }

            await SignalRUserHub.ChangePasswordApiResponse(userHubContext, cmd.ConnectionId, status);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
            await SignalRUserHub.ChangePasswordApiResponse(userHubContext, cmd.ConnectionId, StatusCode.Status500);
        }
    }

    private async Task AutoLoginRequestHandlerAsync(AutoLoginCommand command)
    {
        try
        {
            UserDB? user = dataBaseOperationService.GetUserByName(command.Username);

            IConfigurationSection autoLoginDaysConfig = configuration.GetSection("AutoLoginDays");
            int autoLoginDays = Convert.ToInt32(autoLoginDaysConfig.Value);

            StatusCode status = StatusCode.Status404;
            int userId = -1;
            if (user == null || user.Password != command.Password)
            {
                status = StatusCode.Status4003;
            }
            else if ((DateTime.Now - user.LastLoginTime).TotalDays > autoLoginDays || userCookieDataModel.CheckUserAndSession(user.Id, command.SessionId) == false)
            {
                status = StatusCode.Status4004;
            }
            else
            {
                status = StatusCode.Status200;
                userId = user.Id;
            }

            await SignalRUserHub.LoginApiResponse(userHubContext, command.ConnectionId, status, userId);
        }
        catch (Exception ex)
        {
            await SignalRUserHub.LoginApiResponse(userHubContext, command.ConnectionId, StatusCode.Status4005, -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private void LogoutRequestHandlerAsync(LogoutCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }
        else
        {
            userCookieDataModel.RemoveSession(command.UserId, command.SessionId);
        }

        try
        {
            DateTime time = new(2000, 1, 1);
            dataBaseOperationService.RefreshUserLastLoginTime(command.UserId, time);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task LoginRequestHandlerAsync(LoginCommand command)
    {
        try
        {
            UserDB? user = dataBaseOperationService.GetUserByName(command.Username);
            StatusCode status = StatusCode.Status404;
            int userId = -1;
            if ((user != null) && (user.Password == EncryptService.EncryptPassword(command.Password, user.Salt, EncryptService.SHA256HashFunction)))
            {
                status = StatusCode.Status200;
                userId = user.Id;
                userCookieDataModel.AddCookie(command.SessionId, user.Id, command.DeviceSerialNumber);
                dataBaseOperationService.RefreshUserLastLoginTime(user.Id, DateTime.Now);
            }
            else
            {
                status = StatusCode.Status4002;
            }

            await SignalRUserHub.LoginApiResponse(userHubContext, command.ConnectionId, status, userId);

            if (command.IsRemeberMe && user != null)
            {
                await SignalRUserHub.StayLoginResponse(userHubContext, command.ConnectionId, user.Name, user.Password);
            }
        }
        catch (Exception ex)
        {
            await SignalRUserHub.LoginApiResponse(userHubContext, command.ConnectionId, StatusCode.Status500, -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private void SaveSessionIdCommandHandlerAsync(SaveSessionIdCommand command)
    {
        try
        {
            userCookieDataModel.AddConnection(command.SessionId, command.ConnectionId, command.UserId, command.ConnectionClass);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task FetchUserdataRequestHandlerAsync(FetchUserdataCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            UserDataModel userdata = dataBaseOperationService.FetchUserdata(command.UserId);
            List<string> accessibleLlmModels = dataBaseOperationService.FetchUserAccessibleLlmModels(command.UserId);
            List<AgentTemplateDB> agentList = dataBaseOperationService.FetchAgentTemplates(command.UserId);

            /// <param name="agentList"> Id, Name</param>
            userdata.customAgents = [];
            foreach (AgentTemplateDB agent in agentList)
            {
                // ignore default agent
                if (agent.Name == NameConsts.DefaultAgentName)
                {
                    continue;
                }
                userdata.customAgents.Add(new(agent.Id, agent.Name, agent.UserId, agent.LLMModel, agent.Temperature, agent.AllowedTools, agent.PresetMessage));
            }

            foreach (AgentTemplate officialAgent in AgentTemplates.AgentTemplates.OfficialAgents)
            {
                if (agentList.FirstOrDefault(agentDb => agentDb.Name == officialAgent.Name) == null)
                {
                    officialAgent.Id = dataBaseOperationService.AddAgentTemplate(command.UserId, officialAgent);
                    officialAgent.UserId = command.UserId;
                    if (officialAgent.Name == NameConsts.DefaultAgentName)
                    {
                        return;
                    }
                    userdata.customAgents.Add(officialAgent);
                }
            }

            List<string> connections = userCookieDataModel.GetConnectionsByUserId(command.UserId, (int)UserCookieDataModel.HubConnectionClassEnum.Workflow);
            foreach (string connection in connections)
            {
                eventBus.Publish(new SendSystematicNotificationCommand(command.UserId, connection));
            }
            await SignalRUserHub.FetchUserdataApiResponse(userHubContext, command.ConnectionId, userdata);
        }
        catch (Exception ex)
        {
            await SignalRUserHub.FetchUserdataApiResponse(userHubContext, command.ConnectionId, new UserDataModel(-1, ""));
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task FetchProjectSettingsHandlerAsync(FetchProjectSettingsCommnad command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            string? prjSettings = dataBaseOperationService.FetchProjectSettings(command.UserId, command.PrjId) ?? throw Debug.ShouldNotHappen();
            await SignalRUserSettingsHub.FetchProjectSettingsApiResponse(userSettingsHubContext, command.ConnectionId, command.PrjId, prjSettings);
        }
        catch (Exception ex)
        {
            await SignalRUserSettingsHub.FetchProjectSettingsApiResponse(userSettingsHubContext, command.ConnectionId, command.PrjId, null);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    public async Task UpdateProjectSettingsHandlerAsync(SaveProjectSettingsCommnad command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.UpdateProjectSettings(command.UserId, command.PrjId, command.PrjSettings);

            await SignalRUserSettingsHub.SaveProjectSettingsResponse(userSettingsHubContext, command.ConnectionId);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    public async Task AllowToolCallChangedCommnadHandlerAsync(AllowToolCallChangedCommnad cmd)
    {
        if (userCookieDataModel.CheckUserAndSession(cmd.UserId, cmd.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.UpdateAllowToolCall(cmd.UserId, cmd.IsAllow);

            await SignalRUserSettingsHub.AllowToolCallChangedResponse(userSettingsHubContext, cmd.ConnectionId, cmd.IsAllow);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task CreateProjectRequestHandlerAsync(CreateProjectCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            int projectId = dataBaseOperationService.AddProjectForUser(command.UserId, command.ProjectName, command.ProjectSettings);
            await SignalRChatHub.CreateProjectApiResponse(signalRChatHubContext, command.ConnectionId, projectId, command.ProjectName, command.ProjectSettings);
        }
        catch (Exception ex)
        {
            await SignalRChatHub.CreateProjectApiResponse(signalRChatHubContext, command.ConnectionId, -1, "", "");
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task DeleteProjectCommandHandlerAsync(DeleteProjectCommand cmd)
    {
        if (userCookieDataModel.CheckUserAndSession(cmd.UserId, cmd.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.DeleteProject(cmd.ProjectId);

            List<ChatRoomDB> chatRoomDBs = dataBaseOperationService.GetChatRoomByProjectId(cmd.ProjectId);

            foreach (ChatRoomDB room in chatRoomDBs)
            {
                dataBaseOperationService.DeleteChatRoom(room.Id);
            }

            await SignalRChatHub.DeleteProjectApiResponse(signalRChatHubContext, cmd.ConnectionId, cmd.ProjectId);
        }
        catch (Exception ex)
        {
            await SignalRChatHub.CreateProjectApiResponse(signalRChatHubContext, cmd.ConnectionId, -1, "", "");
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task CreateChatroomRequestHandlerAsync(CreateChatRoomCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            int chatRoomId = dataBaseOperationService.AddChatRoomToProject(command.UserId, command.ProjectId, command.ChatRoomName, false);
            AgentTemplateDB? gptTemplate = dataBaseOperationService.GetAgentTemplateByName(command.UserId, NameConsts.DefaultAgentName) ?? throw new Exception("Default model not found.");
            dataBaseOperationService.AddAgentToChatRoom(chatRoomId, gptTemplate.Id, gptTemplate.LLMModel, gptTemplate.Temperature, gptTemplate.AllowedTools);
            await SignalRChatHub.CreateChatRoomApiResponse(signalRChatHubContext, command.ConnectionId, chatRoomId, command.ProjectId, command.ChatRoomName);
        }
        catch (Exception ex)
        {
            await SignalRChatHub.CreateChatRoomApiResponse(signalRChatHubContext, command.ConnectionId, -1, -1, "");
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task SwitchChatroomRequestHandlerAsync(SwitchChatRoomCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            int projectId = dataBaseOperationService.GetProjectIdByChatRoomId(command.ChatRoomId) ?? throw Debug.ShouldNotHappen();
            ChatRoomDB chatRoomDB = dataBaseOperationService.GetChatRoom(command.ChatRoomId) ?? throw Debug.ShouldNotHappen();
            List<MessageDB> messagesDB = dataBaseOperationService.GetChatRoomMessages(command.ChatRoomId);

            if (chatRoomDB.LastMessageId == 0 && messagesDB.Count > 0)
            {
                dataBaseOperationService.UpdateChatRoomLastMessage(command.ChatRoomId, messagesDB.Last().Id);
                chatRoomDB.LastMessageId = messagesDB.Last().Id;
            }

            dataBaseOperationService.RefreshUserSelectedChatRoomId(command.UserId, command.ChatRoomId, projectId);

            List<int> historyMessagesIdList = [];
            for (int i = 0; i < messagesDB.Count; i++)
            {
                if (messagesDB[i].HistoryMessagesIdList.Count == 0 && i != 0)
                {
                    dataBaseOperationService.UpdateMessageHistory(messagesDB[i].Id, historyMessagesIdList);
                }
                else if (i != 0)
                {
                    break;
                }

                historyMessagesIdList.Add(messagesDB[i].Id);
            }

            List<ChatMessageData> chatMessages = [];
            foreach (MessageDB msgDb in messagesDB)
            {
                ChatMessageData newMsg = ChatMessageData.FromMessageDB(msgDb, 0);

                chatMessages.Insert(0, newMsg);
            }

            await SignalRChatHub.SwitchChatRoomApiResponse(signalRChatHubContext, command.ConnectionId, command.ChatRoomId, projectId, chatMessages, chatRoomDB.LastMessageId);
        }
        catch (Exception ex)
        {
            await SignalRChatHub.SwitchChatRoomApiResponse(signalRChatHubContext, command.ConnectionId, -1, -1, [], -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task SwitchChatRoomBranchCommandHandlerAsync(SwitchChatRoomBranchCommand cmd)
    {
        if (userCookieDataModel.CheckUserAndSession(cmd.UserId, cmd.SessionId) == false)
        {
            return;
        }

        try
        {
            bool success = dataBaseOperationService.UpdateChatRoomLastMessage(cmd.ChatRoomId, cmd.MessageId);

            if (!success)
            {
                return;
            }

            await SignalRChatHub.SwitchChatRoomBranchApiResponse(signalRChatHubContext, cmd.ConnectionId, cmd.ChatRoomId, cmd.MessageId);
        }
        catch (Exception ex)
        {
            await SignalRChatHub.SwitchChatRoomBranchApiResponse(signalRChatHubContext, cmd.ConnectionId, -1, -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private void AddPullRequestUserSubscription(SubscriptonGitlabPullRequestCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.AddOrUpDatePullRequestUserSubscription(true, command.UserId, command.WorkflowId, command.RepositoryURL, command.ShouldAskMe);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private void SavePullRequestContent(RecievePullRequestCommand command)
    {
        try
        {
            // subscriptionId, userId
            List<Tuple<int, int>> subscriptionIdAndUserIds = dataBaseOperationService.GetEveryoneWhosubscribes(SubscriptionClass.GitlabPullRequest, command.MergeRequestInfo["repositoryUri"]);
            foreach (Tuple<int, int> subscriptionIdAndUserId in subscriptionIdAndUserIds)
            {
                int notificationId = dataBaseOperationService.AddSystematicNotification(command.MergeRequestInfo, subscriptionIdAndUserId);

                int userId = subscriptionIdAndUserId.Item2;
                List<string> connections = userCookieDataModel.GetConnectionsByUserId(userId, UserCookieDataModel.HubConnectionClassEnum.Workflow);

                foreach (string connectionId in connections)
                {
                    SystematicNotificationsDB newNotificationsDB = new()
                    {
                        Id = notificationId,
                        Content = command.MergeRequestInfo,
                        SubscriptionId = subscriptionIdAndUserId.Item1,
                        IsProcessed = 0,
                    };

                    eventBus.Publish(new SendSystematicNotificationCommand(userId, connectionId, newNotificationsDB));
                }
            }
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private void RemoveConnectionCommandHandlerAsync(RemoveConnectionCommand cmd)
    {
        try
        {
            userCookieDataModel.RemoveConnectionByConnectionId(cmd.ConnectionId);
        }
        catch (Exception ex)
        {
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task ArchiveChatroomRequestHandlerAsync(ArchiveChatRoomCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.ArchiveChatRoom(command.ChatRoomId);

            int? projectId = dataBaseOperationService.GetProjectIdByChatRoomId(command.ChatRoomId);
            await SignalRUserSettingsHub.ArchiveChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, command.ChatRoomId, projectId ?? -1);
        }
        catch (Exception ex)
        {
            await SignalRUserSettingsHub.ArchiveChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, -1, -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task DeleteChatroomRequestHandlerAsync(DeleteChatRoomCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.DeleteChatRoom(command.ChatRoomId);

            int? projectId = dataBaseOperationService.GetProjectIdByChatRoomId(command.ChatRoomId);
            await SignalRUserSettingsHub.DeleteChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, command.ChatRoomId, projectId ?? -1);
        }
        catch (Exception ex)
        {
            await SignalRUserSettingsHub.DeleteChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, -1, -1);
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }

    private async Task RenameChatRoomRequestHandlerAsync(RenameChatRoomCommand command)
    {
        if (userCookieDataModel.CheckUserAndSession(command.UserId, command.SessionId) == false)
        {
            return;
        }

        try
        {
            dataBaseOperationService.RenameChatRoom(command.ChatRoomId, command.ChatRoomName);

            int? projectId = dataBaseOperationService.GetProjectIdByChatRoomId(command.ChatRoomId);
            await SignalRUserSettingsHub.RenameChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, projectId ?? -1, command.ChatRoomId, command.ChatRoomName);
        }
        catch (Exception ex)
        {
            await SignalRUserSettingsHub.RenameChatRoomApiResponse(userSettingsHubContext, command.ConnectionId, -1, -1, "");
            Debug.LogError(ex?.ToString() ?? "Unknown error");
        }
    }


    #region TODO:
    ///// <summary>
    ///// This service can only process agents that are authorized to move next
    ///// </summary>
    //public override async Task UpdateAsync()
    //{
    //    var orderedAgents = chatContextModel.GetOrderedAndAuthorizedAgents();

    //    foreach (var chatAgent in orderedAgents)
    //    {
    //        var authorizedAndCanMoveNext = chatAgent.MoveNextChatIfQueued();
    //        if (authorizedAndCanMoveNext)
    //        {
    //            // TODO: for now use general toolSet, in the the toolSet should be refactored so that
    //            // toolSets are smaller, and can be combined. 

    //            var requestGuid = await APIComService.RequestChatAsStream(chatAgent, chatAgent.canFuncCall ? toolSetConfig.ToolSet : null);
    //            _apiComRequestHistory.Add(requestGuid, chatAgent.ID);
    //        }
    //    }

    //    // Await the base class's UpdateAsync method, if it does meaningful work
    //    await base.UpdateAsync();
    //}



    //public override Task StartAsync()
    //{
    //    APIComService.OnChatResponse += OpenAiChatResponseHandler;
    //    return Task.CompletedTask;
    //}

    //public override Task OnDestroyAsync()
    //{
    //    APIComService.OnChatResponse -= OpenAiChatResponseHandler;
    //    return Task.CompletedTask;
    //}


    ///// <summary>
    ///// This is to handle any response from a request, no matter human or ai
    ///// It also deal with function call if any
    ///// </summary>
    //private void OpenAiChatResponseHandler(string requestGuid, string chatResponse, List<ToolCall> toolCalls)
    //{
    //    if (_apiComRequestHistory.TryGetValue(requestGuid, out string? requesterId) == false)
    //    {
    //        return;//this guid is not in my request history, not interested. We don't check human here as human might interrupt
    //    }

    //    _apiComRequestHistory.Remove(requestGuid);



    //    if (_chatAgents.ContainsKey(requesterId) == false)
    //    {
    //        Debug.LogError($"Failed to find agent with Id {requesterId}");
    //        return;
    //    }

    //    var targetAgent = _chatAgents[requesterId];

    //    var authorName = ChatStringExtension.NameAsSystemReadable(targetAgent.Name);

    //    //APIComService.RequestTts(response, true);
    //    if (string.IsNullOrEmpty(chatResponse) == false && toolCalls == null) //just assistent msg
    //    {
    //        //this is only to add to chat's chat log
    //        targetAgent.AddChatRespond(response, authorName, null);
    //        targetAgent.RemoveAuthorization();

    //        OnAssistMsgAddedToAgent?.Invoke(_chatAgents[requesterId], chatResponse, null);
    //    }
    //    else if (toolCalls != null) //just tool call or Assistent + ToolCall
    //    {
    //        targetAgent.AddChatRespond(chatResponse, authorName, toolCalls);
    //        var toolCallResult = FunctionCallerService.ToolInvoker(toolCalls);
    //        //I won't trigger on assist msg added to agent yet, this would be triggered by the next time i got reply for this tool message from a assitent role OpenAiAPI reply. 
    //        targetAgent.AddChatRequest(toolCallResult, "ToolCall");
    //    }
    //    else //both msg and tool call is empty. 
    //    {
    //        //this is only to add to chat's chat log, this will not invoke OnAssistMsgAddedToAgent as no one wants to responsed on that. 
    //        targetAgent.AddChatRespond(chatResponse, authorName, null);
    //        targetAgent.RemoveAuthorization();
    //    }
    //}
    #endregion
}